#include <reg52.h>
#include "C51car.h"
#include "LCD.h"

/////////////////////小车运行主程序//////////////////////

void main(void)
{
	
///////////////////////开机初始化////////////////////////
	
     Print_ID()	;                //打印单片机识别号	
     BEEP_music(music,count,5);  //开机提示音	
	 UART_init();                //串口收发初始化
	 Timer0_init();              //定时器0初始化	
	
////////////////////////按键运行/////////////////////////
	
     BIGAN_BUTTON();             //当按下按键后执行避障及循迹程序
	
while(1)
    {	
	
		LED_R = 0;         //程序进入提示
	    LED_L = 0;		
		BEEP = 1;
		delay(50);
		LED_R = 1;
	    LED_L = 1;		
		
     ///////////////////避障及循迹程序//////////////////	
			
	    if(BIZHANG_R ==1 &&BIZHANG_L == 1)//判断是否有障碍物，有障碍物则停止，无障碍物则执行循迹程序
	         {		
               TRACKING();	//循迹程序		
			 }					
	    else if (BIZHANG_R ==1 &&BIZHANG_L == 0)		
		     {
			    BIZHANG_MODE_CHOICE();  //避障模式选择			 
	         }
        else if(BIZHANG_R ==0 &&BIZHANG_L == 1)
             {
				BIZHANG_MODE_CHOICE();  //避障模式选择	 
             }
         else
             {
				BIZHANG_MODE_CHOICE();  //避障模式选择	 
             }			
    }		
}				
////////////////////主函数结束//////////////////////////////
///////////////////////////////////////////////////////////

///////////////////定时器0中断函数////////////////////////
void timer0() interrupt 1 
{
	pwm_t++;
	if(pwm_t == 255)
	{
		pwm_t = 0;
		ENA = ENB = 0;
	}
	if(L_pwm_val == pwm_t)
	{
		ENA = 1;
	}
	if(R_pwm_val == pwm_t)
	{
		ENB = 1;
	}		
}

/////////////////////串口接收中断//////////////////////////
unsigned int receive;
void UART_interrupt() interrupt 4
{
		if(RI==1)
		{

		receive = SBUF;
		UART_sendbyte(0x52);//接收正常，则向电脑正常反馈R-Y
		UART_sendbyte(0x2D);
		UART_sendbyte(0x59);		
		RI=0;
        }	

}
/////////////////////////循迹函数整体////////////////////////////////////////
void TRACKING(void)
{	
	 //////////////////////////转弯模式方案一///////////////////////////////
	 if (MODE_1 ==0 && MODE_2 ==1)
	            {	
					if (XUNJI_R == 1 && XUNJI_L == 1)	//执行直行	
							{
							LCD_Init();				
							LCD_ShowString(1,1,"normal");								
							forward (60,60);
								}
					else if (XUNJI_R == 0 && XUNJI_L == 1)//执行左转
							{
							LCD_Init();
							LCD_ShowString(1,1,"turnleft");								
							turn_left(40,60);	
								}
					else if (XUNJI_R == 1 && XUNJI_L == 0)//执行右转
							{
							LCD_Init();
							LCD_ShowString(1,1,"turnright");								
							turn_right(60,40);
								}
					else                               //执行后退
							{
							LCD_Init();
							LCD_ShowString(1,1,"back");					
							back(40, 40);
							UART_sendbyte(0x66);
							UART_sendbyte(0x65);
								}
				}
		//////////////////////////转弯模式方案二//////////////////////////////	
         else if  (MODE_1 ==1 && MODE_2 ==0)
		        {
			            if (XUNJI_R == 1 && XUNJI_L == 1)	//执行直行	
							{
							LCD_Init();				
							LCD_ShowString(1,1,"normal");								
							forward (60,60);
							    }
					else if (XUNJI_R == 0 && XUNJI_L == 1)//执行左转
							{
							LCD_Init();
							LCD_ShowString(1,1,"turnleft");								
							turn_left_2(40,40);	
								}
					else if (XUNJI_R == 1 && XUNJI_L == 0)//执行右转
							{
							LCD_Init();
							LCD_ShowString(1,1,"turnright");								
							turn_right_2(40,40);
								}
					else                               //执行后退
							{
							LCD_Init();
							LCD_ShowString(1,1,"back");					
							back(40, 40);
							UART_sendbyte(0x66);
							UART_sendbyte(0x65);								
								}
				}
		
       ////////////////////////////////转弯模式方案三///////////////////////////////
		 else  if (MODE_1 == 1 && MODE_2 == 1)
		        {
			                 if (XUNJI_R == 1 && XUNJI_L == 1)	//执行直行	
							{
							LCD_Init();				
							LCD_ShowString(1,1,"normal");								
							forward (60,60);
								}
					else if (XUNJI_R == 0 && XUNJI_L == 1)//执行左转
							{
							LCD_Init();
							LCD_ShowString(1,1,"turnleft");								
							turn_left_3(60);	
								}
					else if (XUNJI_R == 1 && XUNJI_L == 0)//执行右转
							{
							LCD_Init();
							LCD_ShowString(1,1,"turnright");								
							turn_right_3(60);
								}
					else                               //执行后退
							{
							LCD_Init();
							LCD_ShowString(1,1,"back");					
							back(40, 40);
							UART_sendbyte(0x66);
							UART_sendbyte(0x65);								
								}
				}		 
	////////////////////////////转弯模式方案一（备用）//////////////////////////
		else
		        {
			              if (XUNJI_R == 1 && XUNJI_L == 1)	//执行直行	
							{
							LCD_Init();				
							LCD_ShowString(1,1,"normal");								
							forward (60,60);
								}
					else if (XUNJI_R == 0 && XUNJI_L == 1)//执行左转
							{
							LCD_Init();
							LCD_ShowString(1,1,"turnleft");							
							turn_left(40,60);	
								}
					else if (XUNJI_R == 1 && XUNJI_L == 0)//执行右转
							{
							LCD_Init();
							LCD_ShowString(1,1,"turnright");								
							turn_right(60,40);
								}
					else                               //执行后退
							{
							LCD_Init();
							LCD_ShowString(1,1,"back");					
							back(40, 40);
							UART_sendbyte(0x66);
							UART_sendbyte(0x65);								
								}
			    }			 		 
}
/////////////////////////////////////避障模式选择函数////////////////////////////////
void BIZHANG_MODE_CHOICE(void)
{
     if (BIZHANG_MODE == 0)//避障模式一，遇到障碍物即停止
			      {			
                      BEEP = 0;
		              stops();
		              L_pwm_val = 255;//Proteus仿真时，该值时PWM输出为全低位
                      R_pwm_val	= 255;
		              UART_sendbyte(0x90);
		              UART_sendbyte(0x65);
			          UART_sendbyte(0x87);	
	              }
	 else if (BIZHANG_MODE == 1)   //避障模式二，遇到障碍物先后退，然后旋转180^o
			      {
                      BEEP = 0;
		              UART_sendbyte(0x90);
		              UART_sendbyte(0x65);
			          UART_sendbyte(0x87);
					  stops();
					  delay(50);
			          back(30,30);
				      delay(100);
				      turn_left_2(30 ,30);
					  delay(200);
			       }			
}  

////////////////////////////////////////小车运动函数////////////////////////////////////////////   

//小车前进
void forward (uint a ,uint b)  
{
	 L_pwm_val  = 255-(255/100)*a;//运用计算，使PWM值取于（0~100）
     R_pwm_val	= 255-(255/100)*b;
	 L_motor_go;
	 R_motor_go;
}
//小车停止
void stops ()
{
	 L_motor_stop;
	 R_motor_stop;
}
//小车后退
void back (uint c,uint d)
{
  	L_pwm_val = 255-(255/100)*c;
    R_pwm_val	= 255-(255/100)*d;
  	L_motor_back;
	R_motor_back;
}
//小车微左转   方案1
void turn_left(uint e ,uint f)
{
	  L_pwm_val = 255-(255/100)*e;
      R_pwm_val	= 255-(255/100)*f;
		L_motor_go;
		R_motor_go;
}
//小车微右转  方案1
void turn_right(uint g ,uint h)
{
	 L_pwm_val  = 255-(255/100)*g;///L  zuo
   R_pwm_val	= 255-(255/100)*h;
	 R_motor_go;
	 L_motor_go;
}
//小车左转   方案2
void turn_left_2(uint i ,uint j)
{
	L_pwm_val  = 255-(255/100)*i;
    R_pwm_val	= 255-(255/100)*j;
	R_motor_go;
	L_motor_back;
}
//小车右转   方案2
void turn_right_2(uint k ,uint l)
{
	L_pwm_val  = 255-(255/100)*k;
   R_pwm_val	= 255-(255/100)*l;
	R_motor_back;
	L_motor_go;
}
//小车左转   方案3
void turn_left_3(uint n)
{
	R_pwm_val	= 255-(255/100)*n;
    L_motor_stop;
	R_motor_go;
}
//小车右转   方案3
void turn_right_3(uint m)
{
	L_pwm_val	= 255-(255/100)*m;
	R_motor_stop;
	L_motor_go;
}
///////////////////////////////////////////////////////////////////////
///////////////////////////按键启动函数////////////////////////////////
void BIGAN_BUTTON(void)
{
   for(;;)
   {	
	  LED_L = 1;
	  LED_R = 0;
	  LCD_Init();
	  LCD_ShowString(1,1,"hello");//用于测试代码运行情况
	  LCD_ShowString(2,1,"ready to go");
	
		 if (KEY == 0)
		   {			
			delay(5);//按键消除抖动			
			    if(KEY == 0)
			        {
					   LED_L = 0;
					   LED_R = 1;
					   BEEP = 0;
				     while(! KEY);		//松手运行		
				     break;
			        }
		   }
    }	
}
////////////////////////PWM发生定时器0初始化////////////////////////
void Timer0_init()
{

		TMOD |= 0x02 ;//8位自动重装模式
		TH0 = 220  ; //36次溢出
		TL0 = 220  ; //11.0592M 下占空比最大值为256，输出100HZ
		TR0 = 1 ; //启动定时器0
	    ET0 = 1 ; //允许定时器0中断
		EA  = 1 ; //总中断允许打开	
     //	PT0H = 0;          
	    PT0 = 1;//此时定时器0优先级为较低优先级	
}
/////////////////////部分功能函数////////////////////////////// 
//延迟函数 时间=m *1ms
void delay (unsigned int m)
{
		unsigned int a,b;
	    for(a=m;a>0;a--);
		for(b=120;b>0;b--);  //循环120大概1ms
}
//延迟10ms
void Delay10ms()		//@11.0592MHz
{
	    unsigned char i, j;
	    i = 18;
	    j = 235;
	   do
	     {
		    while (--j);
	     } 
	  while (--i);
}
//蜂鸣器函数  BEEP 0响，1不响
//在1*（c+d）ms内响count次
void pulse_BEEP (unsigned int count,unsigned int c,unsigned int d)
{
	 int i;
	 for(i=0;i<count ;i++)
	{
		BEEP =1;
		delay(c);
		BEEP =0;
		delay(d);
	}
}
//蜂鸣器延时模块
void delay_op(unsigned int w)
{
	int m=0;
	for(;m<w;)
   {
 	m++;
    }
}
//蜂鸣器音调功能函数
void BEEP_music(unsigned int *ha ,unsigned int *hei,unsigned int length)//运用指针传递数组
{
	unsigned int i,u,k,l;
	i=u=0;
        for(l=0;l<length;l++)
	    {
	       for(k=0;k<ha[i];k++)
	        {
				BEEP = 0;
				delay_op(hei[u]);
				BEEP = 1;
				delay_op(hei[u]);
			}
				i++;
				u++;
		}
}
//打印单片机唯一识别号ID
void Print_ID(void)
{
		    unsigned char code *p;	
		p =(unsigned char code *)0xFF8;	
			LCD_Init();
			LCD_ShowHexNum(1,1,*p,2);
			LCD_ShowHexNum(1,3,*(p+1),2);
			LCD_ShowHexNum(1,5,*(p+2),2);
			LCD_ShowHexNum(1,7,*(p+3),2);
			LCD_ShowHexNum(1,9,*(p+4),2);
			LCD_ShowHexNum(1,11,*(p+5),2);
			LCD_ShowHexNum(1,13,*(p+6),2);
}
///////////////////////串口相关功能函数///////////////////////////
//串口设置
void UART_init(void)		//4800bps@11.0592MHz
{
	PCON |= 0x80;		//使能波特率倍速位SMOD
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xF4;		//设置定时初始值
	TH1 = 0xF4;		//设置定时重载值
	ET1 = 0;		//禁止定时器%d中断
	TR1 = 1;		//定时器1开始计时
	EA=1;
	ES=1;	
	IP = 0x12;//	
	//中断优先级控制寄存器IPH为不可位寻址
	//PSH =1;
	PS =1;//此时串口中断为最高优先级	
}
//单片机串口发送字节（byte）
void UART_sendbyte(unsigned char byte)
{
	SBUF = byte;
	while(TI==0);
	TI =0;
}
/////////////////////////////////////////////////////////////////
